/**
 * 泛型 重点 难点 
 * 在定义函数、接口和类的时候，不预先定具体的类型而是使用的时候指定
 * 泛型也像是一个参数
 */
function createArray<T>(length:number,value:T):T[]{
   let result:T[] = [];
   for(let i=0;i<length;i++){
      result[i] = value;
   }
   return result;
}
let result = createArray<string>(3,'x');
// let result1 = createArray<number>(3,'x');限定了类型是number不能传'x'
console.log(result);

//类数组
function sum(...args:number[]){
  let args2:IArguments = arguments;
  for(let i=0;i<args.length;i++){
    console.log(args[i]);
  }
}
sum(1,2,3);

//泛型类
class MyArray<T>{
  private list: T[] = [];
  add(value: T){
    this.list.push(value);
  }
}
let arr = new MyArray<number>();
arr.add(2);

//接口里使用泛型
// interface Calculate {
//   <T>(a:T,b:T): T
// }
// let add:Calculate = function(a,b){
//   return a;
// }
// add(2,3)

interface Calculate<A> {
  <B>(a:A,b:B): A
}
let add:Calculate<number> = <B>(a:number,b:B)=>{
  return a;
}
add<string>(2,'3')

//默认泛型
interface Calculate2<A=number> {
  <B>(a:A,b:B): A
}
let add2:Calculate2 = <B>(a:number,b:B)=>{
  return a;
}
add2<string>(2,'3')

//泛型约束
// function logger<T>(value:T){
//   console.log(value.length); //默认情况下 ，不能调用泛型上的任何属性和方法，因为在定义的时候不知道会传入什么值
// }
interface lengthWise{
  length: number
} //用接口约束泛型

function logger<T extends lengthWise>(value:T){
  console.log(value.length); //默认情况下 ，不能调用泛型上的任何属性和方法，因为在定义的时候不知道会传入什么值
}
logger<string>('d');

//泛型类型别名
type Cart<T> = {list: T[]} | T[];
let c1:Cart<string> = {list: ['1','2']};
let c2:Cart<number> = [2,3,4];

